package com.jqh.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jqh.demo.entity.AclMenu;
import com.jqh.demo.entity.AclRole;
import com.jqh.demo.entity.AclRoleMenu;
import com.jqh.demo.mapper.AclMenuMapper;
import com.jqh.demo.service.AclMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jqh.demo.service.AclRoleMenuService;
import com.jqh.demo.service.AclRoleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.acl.Acl;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author jqh
 * @since 2021-05-08
 */
@Service
public class AclMenuServiceImpl extends ServiceImpl<AclMenuMapper, AclMenu> implements AclMenuService {

    @Autowired
    private AclRoleMenuService aclRoleMenuService;

    @Autowired
    private AclRoleService aclRoleService;

    @Override
    public List<AclMenu> getAllMenu() {
        //获取全部未构建的菜单
        List<AclMenu> menuList = baseMapper.selectList(new QueryWrapper<AclMenu>().orderByAsc("id"));
        //构建成树形结构后的树形菜单
        List<AclMenu> result=build(menuList);
        //返回构建的树形菜单
        return result;
    }

    @Override
    public boolean removeMenuAndChildrenById(String id) {
        //创建集合，用于封装要删除的菜单id
        List<String> idList=new ArrayList<>();
        //创建封装要删除的子菜单id的方法
        this.selectIds(id,idList);
        //当前id加入其中，并执行删除方法。
        idList.add(id);
        baseMapper.deleteBatchIds(idList);
        this.delRoleWithMenuByMenuId(idList);
        return true;
    }
    //删除中间表记录
    private void delRoleWithMenuByMenuId(List<String> idList) {
        for (String id : idList) {
            aclRoleMenuService.remove(new QueryWrapper<AclRoleMenu>().eq("menu_id",id));
        }
    }

    @Override
    public void giveRoleMenu(String roleId, String[] menuIds) {
        //先删除再进行分配
        aclRoleMenuService.remove(new QueryWrapper<AclRoleMenu>().eq("role_id", roleId));

        List<AclRoleMenu> list=new ArrayList<>();
        for (String menuId : menuIds) {
            AclRoleMenu aclRoleMenu=new AclRoleMenu();
            aclRoleMenu.setRoleId(roleId);
            aclRoleMenu.setMenuId(menuId);
            list.add(aclRoleMenu);
        }
        aclRoleMenuService.saveBatch(list);
    }

    @Override
    public List<AclMenu> getMenuByRoleId(String roleId) {
        List<AclMenu> allMenu = baseMapper.selectList(new QueryWrapper<AclMenu>().orderByAsc("id"));
        List<AclRoleMenu> aclRoleMenuList = aclRoleMenuService.list(new QueryWrapper<AclRoleMenu>().eq("role_id", roleId));
        List<AclMenu> roleMenu=new ArrayList<>();
        //循环，判断取出角色所拥有的菜单记录
        for (AclMenu aclMenu : allMenu) {
            for (AclRoleMenu aclRoleMenu : aclRoleMenuList) {
                if(aclMenu.getId().equals(aclRoleMenu.getMenuId())){
                    roleMenu.add(aclMenu);
                }
            }
        }
        List<AclMenu> resultMenu = build(roleMenu);
        return resultMenu;
    }

    @Override
    public List<AclMenu> getAllOpeMenuByUserId(String userId) {
        //指定用户id获取菜单
        List<AclMenu> operMenu=baseMapper.getAllOpeMenuByUserId(userId);
        //将获取的菜单进行树形菜单构建
        List<AclMenu> menuList = build(operMenu);
        return menuList;
    }

    @Override
    public List<AclMenu> getDefaultMenuList() {
        //1.获取角色为“默认菜单”的id
        AclRole one = aclRoleService.getOne(new QueryWrapper<AclRole>().eq("role_name", "默认菜单"));
        //2.查询其拥有的菜单
        List<AclMenu> defaultMenu=baseMapper.getDefaultMenuList(one.getId());
        //3.构建树形菜单
        List<AclMenu> resultMenu = build(defaultMenu);
        return resultMenu;
    }

    private void selectIds(String id, List<String> idList) {
        //查询pid为id的所有菜单，且只选择id字段。
        List<AclMenu> menuList = baseMapper.selectList(new QueryWrapper<AclMenu>().eq("pid", id).select("id"));
        //遍历菜单
        for (AclMenu aclMenu : menuList) {
            String menuId=aclMenu.getId();
            //添加当前的菜单id到idList
            idList.add(menuId);
            this.selectIds(menuId,idList);
        }
    }

    /**
     * @param menuList
     * @return
     * <p>构建树形菜单</p>
     */
    private static List<AclMenu> build(List<AclMenu> menuList) {
        List<AclMenu> treeMenu=new ArrayList<>();
        //遍历,查出pid为0的一级菜单
        for (AclMenu menu : menuList) {
            if("0".equals(menu.getPid())){
                //给一级菜单设置层级
                menu.setLevel(1);
                //添加到树形菜单上,buildChild传入一级菜单和全部未构建的菜单，便于寻找一级菜单下的子菜单。
                treeMenu.add(findChild(menu,menuList));
            }
        }
        return treeMenu;
    }

    private static AclMenu findChild(AclMenu menu, List<AclMenu> menuList) {
        //给上级菜单设置个空的子菜单空间
        menu.setChildren(new ArrayList<AclMenu>());
        //遍历未构建菜单
        for (AclMenu aclMenu : menuList) {
            //全部菜单的pid 与 一级菜单的id 是否存在相等的情况，相等时，即是一级菜单的子菜单。
            if(aclMenu.getPid().equals(menu.getId())){
                //获取一级菜单的level值，加一表示一级菜单的下级菜单
                int level=menu.getLevel()+1;
                //二级菜单设置level值
                aclMenu.setLevel(level);
                if(menu.getChildren()==null){
                    menu.setChildren(new ArrayList<AclMenu>());
                }
                //传入上级菜单和未构建菜单，便于继续寻找下级菜单
                menu.getChildren().add(findChild(aclMenu,menuList));
            }
        }
        return menu;
    }
}
